package com.socio.resources;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
import com.google.gson.Gson;
import com.socio.behaviors.DAOBehavior;
import com.socio.behaviors.DayKeyBehavior;
import com.socio.behaviors.UserUDIDBehavior;
import com.socio.model.ClientUser;
import com.socio.model.Day;
import com.socio.model.User;
import com.socio.model.responses.DayLeaderboardAlltimeResponse;
import com.socio.model.responses.DayLeaderboardResponse;
import com.socio.utils.FieldAccessor.FieldAccessorField;

@Path("/day")
public class DayResource {

	private static final Gson gson = new Gson();
	
	@SuppressWarnings("unchecked")
	@Path("/leaderboard")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
	public String getLeaderboard(@QueryParam("dayTime") @DefaultValue("-1") long dayTime, 
			@QueryParam("udid") String udid) {
		
		// setup
		DayLeaderboardResponse response = new DayLeaderboardResponse(false);
		if(dayTime < 0)
			return gson.toJson(response);
        DAOBehavior dayDAO = new DayKeyBehavior();
        DAOBehavior userDAO = new UserUDIDBehavior();
        Queue queue = QueueFactory.getDefaultQueue();
        TaskOptions taskOptions = TaskOptions.Builder.withUrl("/resources/twitter/lasttweet")
        	.param("udid", udid).method(Method.GET);
		
        // get 3 days with highest quickScores
        String filter = "startTime == startTimeParam";
        String declareParameters = "Long startTimeParam";
        String ordering = "quickScore desc";
        Long[] queryRange = new Long[]{0L,3L};
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("startTimeParam", dayTime);
        List<FieldAccessorField> touchFields = Arrays.asList(FieldAccessorField.DayUser);
        Object result = dayDAO.execute(filter, declareParameters, ordering, queryRange, parameterMap, touchFields);
        List<Day> dbDays = (List<Day>)result;
        if(dbDays.isEmpty() || dbDays.get(0) == null) {
        	response.setSuccess(true);
        	return gson.toJson(response);
        }
		
		// check to see if days contain user with udid (if specified)
        List<ClientUser> resultingUsers = new ArrayList<ClientUser>();
        boolean containsRequester = false;
        if(udid == null || udid.isEmpty())
        	containsRequester = true;
        for(Day day : dbDays) {
        	ClientUser resultingUser = day.getUser().getClientUser();
        	resultingUser.setQuickScore(day.getQuickScore());
        	if(!containsRequester && day.getUser().getAndroidUDID().equalsIgnoreCase(udid)) {
        		resultingUser.setNickname("You");
        		if(!day.getUser().getFacebookID().isEmpty())
            		resultingUser.setScoring(true);
        		containsRequester = true;
        	}
        	
        	resultingUsers.add(resultingUser);
        }
        if(containsRequester) {
        	response.setSuccess(true);
        	response.setUsers(resultingUsers);
        	queue.add(taskOptions);
        	return gson.toJson(response);
        }
		
		// Get user and add them as a fourth
    	result = userDAO.read(udid, null);
        List<User> dbUser = (List<User>)result;
        if(!dbUser.isEmpty() && dbUser.get(0) != null) {
        	User user = (User)dbUser.get(0);
        	ClientUser requestingUser = user.getClientUser();
        	requestingUser.setQuickScore(0);
        	requestingUser.setNickname("You");
        	if(!user.getDays().isEmpty()) {
            	Day mostRecentScoringDay = user.getDays().iterator().next();
            	if(mostRecentScoringDay.getStartTime() == dayTime)
            		requestingUser.setQuickScore(mostRecentScoringDay.getQuickScore());
        	}
        	
        	// check to see if user is somehow earning points
        	if(!user.getFacebookID().isEmpty())
        		requestingUser.setScoring(true);
            resultingUsers.add(requestingUser);
        }
		
        queue.add(taskOptions);
        response.setSuccess(true);
    	response.setUsers(resultingUsers);
    	return gson.toJson(response);
	}
	
	@SuppressWarnings("unchecked")
	@Path("/leaderboard/alltime")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
	public String getLeaderboard(@QueryParam("udid") String udid) {
	
		// set up behaviors
        DAOBehavior userDAO = new UserUDIDBehavior();
        DayLeaderboardAlltimeResponse response = new DayLeaderboardAlltimeResponse(false);
		
        // get 3 users with highest quickScores
        String ordering = "quickScore desc";
        Long[] queryRange = new Long[]{0L,3L};
        Object result = userDAO.execute(null, null, ordering, queryRange, null, null);
        List<User> dbUsers = (List<User>)result;
        if(dbUsers.isEmpty() || dbUsers.get(0) == null) {
        	response.setSuccess(true);
        	return gson.toJson(response);
        }
        
        // check to see if days contain user with udid (if specified)
        List<ClientUser> resultingUsers = new ArrayList<ClientUser>();
        boolean containsRequester = false;
        if(udid == null || udid.isEmpty())
        	containsRequester = true;
        for(User user : dbUsers) {
        	ClientUser resultingUser = user.getClientUser();
        	if(!containsRequester && user.getAndroidUDID().equalsIgnoreCase(udid)) {
        		resultingUser.setNickname("You");
        		if(!user.getFacebookID().isEmpty())
        			resultingUser.setScoring(true);
        		containsRequester = true;
        	}
        	
        	resultingUsers.add(resultingUser);
        }
        if(containsRequester) {
        	response.setSuccess(true);
        	response.setUsers(resultingUsers);
        	return gson.toJson(response);
        }
        
        // if user not part of top 3 get them and add them as a fourth
    	result = userDAO.read(udid, null);
        List<User> dbUser = (List<User>)result;
        if(!dbUser.isEmpty() && dbUser.get(0) != null) {
        	User user = (User)dbUser.get(0);
        	ClientUser requestingUser = user.getClientUser();
        	requestingUser.setNickname("You");
        	
        	// check to see if user is somehow earning points
        	if(!user.getFacebookID().isEmpty())
        		requestingUser.setScoring(true);
            resultingUsers.add(requestingUser);
        }
		
        response.setSuccess(true);
    	response.setUsers(resultingUsers);
    	return gson.toJson(response);
	}
}
